﻿
-- BEGIN LOCAL VARIABLES --

local TT_VERSION = "1.5.a";

local TTFrame = nil;
local activeBG = nil;
local activeBGID = nil;
local activeTeamSize = 0;
local elapsedUpdateRequest = 0;
local frequencyUpdateRequest = 10;
local timeScoreUpdated = 0;
local expiration = 0;

local playerTable = {};
local averageDamage = 0;
local averageHeals = 0;
local maxHonor = 0;

local locationTableAV = {};
local locationTableAB = {};
local locationTableWSG = {};
local locationTableEOTS = {};
local locationTableIOC = {};
local locationTableSOTA = {};


-- END LOCAL VARIABLES --



-- BEGIN SAVED VARIABLES --

TT_SavedVars = {};

TT_SavedVars.enableReporting = true;
TT_SavedVars.announceReports = true;
TT_SavedVars.minPercentEffort = 10;
TT_SavedVars.pctDefenseBonus = 50;
TT_SavedVars.pctCaptureBonus = 100;
TT_SavedVars.timeLeaveEntrance = 1;
TT_SavedVars.timeBeforeReport = 3;

-- END SAVED VARIABLES --



-- BEGIN CONFIG UI FUNCTIONS --

function TT_ConfigFrame_chkEnable_OnClick()
	if(this:GetChecked()) then
		TT_SavedVars.enableReporting = true;
	else
		TT_SavedVars.enableReporting = false;
	end
	if(TT_SavedVars.enableReporting) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> AFK Reporting Enabled.");
	else
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> AFK Reporting Disabled.");
	end
end

function TT_ConfigFrame_chkAnnounce_OnClick()
	if(this:GetChecked()) then
		TT_SavedVars.announceReports = true;
	else
		TT_SavedVars.announceReports = false;
	end
	if(TT_SavedVars.announceReports) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Reports sent will be displayed here.");
	else
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Reports sent will be hidden. The Blizzard API may still produce notifications.");
	end
end

function TT_ConfigFrame_sldPercentEffort_OnChange()
	TT_SavedVars.minPercentEffort = this:GetValue();
end

function TT_ConfigFrame_sldPercentEffort_PostChange()
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Minimum effort to not be considered AFK: " .. TT_SavedVars.minPercentEffort .. "%. (percentage of average effort)");
end

function TT_ConfigFrame_sldDefenseBonus_OnChange()
	TT_SavedVars.pctDefenseBonus = this:GetValue();
end

function TT_ConfigFrame_sldDefenseBonus_PostChange()
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Players defending key nodes will be awarded bonus effort: " .. TT_SavedVars.pctDefenseBonus .. "%. (adjusted by percentage of total time spent defending)");
end

function TT_ConfigFrame_sldCaptureBonus_OnChange()
	TT_SavedVars.pctCaptureBonus = this:GetValue();
end

function TT_ConfigFrame_sldCaptureBonus_PostChange()
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Players capturing/recovering flags will be awarded bonus effort: " .. TT_SavedVars.pctCaptureBonus .. "%. (per capture/recovery point)");
end

function TT_ConfigFrame_sldEntranceTime_OnChange()
	TT_SavedVars.timeLeaveEntrance = this:GetValue();
end

function TT_ConfigFrame_sldEntranceTime_PostChange()
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Players still in the entrance area more than " .. TT_SavedVars.timeLeaveEntrance .. " minute(s) after gates open/joining (whichever is later) can be considered for AFK reporting. (Does not apply to WSG.)");
end

function TT_ConfigFrame_sldReportTime_OnChange()
	TT_SavedVars.timeBeforeReport = this:GetValue();
end

function TT_ConfigFrame_sldReportTime_PostChange()
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Players cannot be considered for AFK reporting until " .. TT_SavedVars.timeBeforeReport .. " minutes after gates open/joining (whichever is later). (Additional time is granted in AV depending on the player's location.)");
end

function TT_ConfigFrame_btnListLeechers_OnClick()
	TT_DisplayLeechers();
end

function TT_ConfigFrame_btnAnnounceLeechers_OnClick()
	TT_AnnounceLeechers();
end

-- END CONFIG UI FUNCTIONS --



-- BEGIN LOCATION TABLES --

function TT_InitLocations_AV()
	locationTableAV = {};
	locationTableAV.loc_error =		{ index = 0, priority = 1, minX = 0, maxX = 0, minY = 0, maxY = 0, locationName = "LOCATION UNKNOWN" };
	locationTableAV.loc_alli_cave =		{ index = 1, priority = 1, minX = 52, maxX = 99, minY = 0, maxY = 12, locationName = "Alliance Cave" };
	locationTableAV.loc_alli_mine =		{ index = 2, priority = 1, minX = 47, maxX = 51, minY = 0, maxY = 12, locationName = "Irondeep Mine" };
	locationTableAV.loc_dbn_tw =		{ index = 3, priority = 1, minX = 44, maxX = 46, minY = 13, maxY = 15, locationName = "DB North Tower" };
	locationTableAV.loc_dbs_tw =		{ index = 4, priority = 1, minX = 43, maxX = 44, minY = 17, maxY = 19, locationName = "DB South Tower" };
	locationTableAV.loc_sp_gy =		{ index = 5, priority = 1, minX = 48, maxX = 49, minY = 13, maxY = 16, locationName = "Stormpike Graveyard" };
	locationTableAV.loc_airstrip =		{ index = 6, priority = 1, minX = 52, maxX = 99, minY = 13, maxY = 30, locationName = "Alliance Airstrip" };
	locationTableAV.loc_sp_road =		{ index = 7, priority = 1, minX = 50, maxX = 51, minY = 21, maxY = 28, locationName = "Stormpike Road" };
	locationTableAV.loc_harpy_valley =	{ index = 8, priority = 1, minX = 41, maxX = 49, minY = 21, maxY = 28, locationName = "Harpy Valley" };
	locationTableAV.loc_harpy_cave =	{ index = 9, priority = 1, minX = 0, maxX = 40, minY = 28, maxY = 40, locationName = "Harpy Cave" };
	locationTableAV.loc_iw_tw =		{ index = 10, priority = 1, minX = 50, maxX = 51, minY = 29, maxY = 31, locationName = "Icewing Tower" };
	locationTableAV.loc_sh_gy =		{ index = 11, priority = 1, minX = 51, maxX = 54, minY = 33, maxY = 36, locationName = "Stonehearth Graveyard" };
	locationTableAV.loc_sh_tw =		{ index = 12, priority = 1, minX = 52, maxX = 53, minY = 42, maxY = 44, locationName = "Stonehearth Tower" };
	locationTableAV.loc_balinda =		{ index = 13, priority = 1, minX = 47, maxX = 49, minY = 36, maxY = 41, locationName = "Stonehearth Outpost" };
	locationTableAV.loc_sf_gy =		{ index = 14, priority = 1, minX = 43, maxX = 45, minY = 44, maxY = 46, locationName = "Snowfall Graveyard" };
	locationTableAV.loc_galv =		{ index = 15, priority = 1, minX = 45, maxX = 46, minY = 54, maxY = 59, locationName = "Iceblood Garrison" };
	locationTableAV.loc_ib_tw =		{ index = 16, priority = 1, minX = 47, maxX = 48, minY = 58, maxY = 59, locationName = "Iceblood Tower" };
	locationTableAV.loc_ib_gy =		{ index = 17, priority = 1, minX = 49, maxX = 51, minY = 58, maxY = 61, locationName = "Iceblood Graveyard" };
	locationTableAV.loc_tp_tw =		{ index = 18, priority = 1, minX = 50, maxX = 51, minY = 64, maxY = 66, locationName = "Tower Point" };
	locationTableAV.loc_horde_cave =	{ index = 19, priority = 1, minX = 53, maxX = 99, minY = 68, maxY = 71, locationName = "Horde Cave" };
	locationTableAV.loc_horde_mine =	{ index = 20, priority = 1, minX = 0, maxX = 47, minY = 63, maxY = 72, locationName = "Coldtooth Mine" };
	locationTableAV.loc_fw_gy =		{ index = 21, priority = 1, minX = 49, maxX = 51, minY = 75, maxY = 78, locationName = "Frostwolf Graveyard" };
	locationTableAV.loc_fww_tw =		{ index = 22, priority = 1, minX = 48, maxX = 48, minY = 84, maxY = 84, locationName = "West Frostwolf Tower" };
	locationTableAV.loc_fwe_tw =		{ index = 23, priority = 1, minX = 49, maxX = 49, minY = 84, maxY = 84, locationName = "East Frostwolf Tower" };
	locationTableAV.loc_gnoll_cave =	{ index = 24, priority = 1, minX = 52, maxX = 99, minY = 88, maxY = 99, locationName = "Gnoll Cave" };
	locationTableAV.loc_db_keep =		{ index = 25, priority = 2, minX = 0, maxX = 46, minY = 0, maxY = 29, locationName = "Dun Baldar Keep" };
	locationTableAV.loc_fw_keep =		{ index = 26, priority = 2, minX = 0, maxX = 51, minY = 77, maxY = 99, locationName = "Frostwolf Keep" };
	locationTableAV.loc_db_valley =		{ index = 27, priority = 3, minX = 0, maxX = 99, minY = 0, maxY = 31, locationName = "Dun Baldar Valley" };
	locationTableAV.loc_fos_valley =	{ index = 28, priority = 3, minX = 0, maxX = 99, minY = 32, maxY = 61, locationName = "Field of Strife" };
	locationTableAV.loc_fw_valley =		{ index = 29, priority = 3, minX = 0, maxX = 99, minY = 62, maxY = 99, locationName = "Frostwolf Valley" };
end


function TT_InitLocations_AB()
	locationTableAB = {};
	locationTableAB.loc_error =		{ index = 0, priority = 1, minX = 0, maxX = 0, minY = 0, maxY = 0, locationName = "LOCATION UNKNOWN" };
	locationTableAB.loc_alli_entry =	{ index = 1, priority = 1, minX = 28, maxX = 34, minY = 9, maxY = 19, locationName = "Trollbane Hall" };
	locationTableAB.loc_horde_entry =	{ index = 2, priority = 1, minX = 64, maxX = 70, minY = 66, maxY = 74, locationName = "Defiler's Den" };
	locationTableAB.loc_stables =		{ index = 3, priority = 1, minX = 33, maxX = 39, minY = 26, maxY = 32, locationName = "Stables" };
	locationTableAB.loc_mine =		{ index = 4, priority = 1, minX = 54, maxX = 60, minY = 26, maxY = 35, locationName = "Mine" };
	locationTableAB.loc_blacksmith =	{ index = 5, priority = 1, minX = 44, maxX = 50, minY = 41, maxY = 48, locationName = "Blacksmith" };
	locationTableAB.loc_mill =		{ index = 6, priority = 1, minX = 35, maxX = 42, minY = 53, maxY = 62, locationName = "Lumbermine" };
	locationTableAB.loc_farm =		{ index = 7, priority = 1, minX = 54, maxX = 59, minY = 56, maxY = 65, locationName = "Farm" };
	locationTableAB.loc_ab_valley =		{ index = 8, priority = 2, minX = 0, maxX = 100, minY = 0, maxY = 100, locationName = "Arathi Basin" };
end


function TT_InitLocations_WSG()
	locationTableWSG = {};
	locationTableWSG.loc_error =		{ index = 0, priority = 1, minX = 0, maxX = 0, minY = 0, maxY = 0, locationName = "LOCATION UNKNOWN" };
	locationTableWSG.loc_alli_base =	{ index = 1, priority = 1, minX = 47, maxX = 51, minY = 11, maxY = 20, locationName = "Silverwing Hold" };
	locationTableWSG.loc_horde_base =	{ index = 2, priority = 1, minX = 50, maxX = 54, minY = 84, maxY = 93, locationName = "Warsong Lumber Mill" };
	locationTableWSG.loc_wsg_valley =	{ index = 3, priority = 2, minX = 0, maxX = 100, minY = 0, maxY = 100, locationName = "Warsong Gulch" };
end


function TT_InitLocations_EOTS()
	locationTableEOTS = {};
	locationTableEOTS.loc_error =		{ index = 0, priority = 1, minX = 0, maxX = 0, minY = 0, maxY = 0, locationName = "LOCATION UNKNOWN" };
	locationTableEOTS.loc_alli_entry =	{ index = 1, priority = 1, minX = 0, maxX = 100, minY = 0, maxY = 32, locationName = "Alliance Entry Area" };
	locationTableEOTS.loc_horde_entry =	{ index = 2, priority = 1, minX = 0, maxX = 100, minY = 66, maxY = 100, locationName = "Horde Entry Area" };
	locationTableEOTS.loc_mage_tower =	{ index = 3, priority = 1, minX = 39, maxX = 42, minY = 39, maxY = 43, locationName = "Mage Tower" };
	locationTableEOTS.loc_dranei_ruins =	{ index = 4, priority = 1, minX = 53, maxX = 57, minY = 38, maxY = 44, locationName = "Dranei Ruins" };
	locationTableEOTS.loc_fel_reaver =	{ index = 5, priority = 1, minX = 38, maxX = 42, minY = 54, maxY = 60, locationName = "Fel Reaver" };
	locationTableEOTS.loc_bloodelf_tower =	{ index = 6, priority = 1, minX = 54, maxX = 57, minY = 55, maxY = 59, locationName = "Bloodelf Tower" };
	locationTableEOTS.loc_eots_valley =	{ index = 7, priority = 2, minX = 0, maxX = 100, minY = 0, maxY = 100, locationName = "Eye of the Storm" };
end


function TT_InitLocations_IoC()
	locationTableIoC = {};
	locationTableIoC.loc_error = { index = 0, priority = 1, minX = 0, maxX = 0, minY = 0, maxY = 0, locationName = "LOCATION UNKNOWN" };
    locationTableIoC.loc_alli_flag = { index = 1, priority = 1, minX = 49, maxX = 50, minY = 79, maxY = 80, locationName = "Alliance Flag" };
    locationTableIoC.loc_alli_turw = { index = 2, priority = 1, minX = 48, maxX = 49, minY = 73, maxY = 74, locationName = "Alliance West Turret" };
    locationTableIoC.loc_alli_ture = { index = 3, priority = 1, minX = 53, maxX = 54, minY = 73, maxY = 74, locationName = "Alliance East Turret" };
    locationTableIoC.loc_hord_flag = { index = 4, priority = 1, minX = 61, maxX = 67, minY = 81, maxY = 86, locationName = "Horde Flag" };
    locationTableIoC.loc_hord_turw = { index = 5, priority = 1, minX = 61, maxX = 67, minY = 81, maxY = 86, locationName = "Horde West Turret" };
    locationTableIoC.loc_hord_ture = { index = 6, priority = 1, minX = 61, maxX = 67, minY = 81, maxY = 86, locationName = "Horde East Turret" };
    locationTableIoC.loc_quarry = { index = 7, priority = 1, minX = 61, maxX = 67, minY = 81, maxY = 86, locationName = "Quarry" };
    locationTableIoC.loc_workshop = { index = 8, priority = 1, minX = 48, maxX = 52, minY = 51, maxY = 55, locationName = "Workshop" };
    locationTableIoC.loc_docks = { index = 9, priority = 1, minX = 32, maxX = 36, minY = 53, maxY = 57, locationName = "Docks" };
    locationTableIoC.loc_hangar = { index = 10, priority = 1, minX = 56, maxX = 60, minY = 49, maxY = 53, locationName = "Hangar" };
    locationTableIoC.loc_refinery = { index = 11, priority = 1, minX = 34, maxX = 38, minY = 27, maxY = 31, locationName = "Refinery" };
    locationTableIoC.loc_alli_keep = { index = 12, priority = 2, minX = 48, maxX = 54, minY = 72, maxY = 84, locationName = "Alliance Keep" };
    locationTableIoC.loc_hord_keep = { index = 13, priority = 2, minX = 45, maxX = 52, minY = 20, maxY = 31, locationName = "Horde Keep" };
    locationTableIoC.loc_ioc_field = { index = 14, priority = 3, minX = 20, maxX = 95, minY = 20, maxY = 90, locationName = "Isle of Conquest Field" };
end 

function TT_InitLocations_SOTA()
    locationTableSOTA = {};
	locationTableSOTA.loc_error = { index = 0, priority = 1, minX = 0, maxX = 0, minY = 0, maxY = 0, locationName = "LOCATION UNKNOWN" };
    locationTableSOTA.loc_west_beach = { index = 1, priority = 1, minX = 38, maxX = 43, minY = 24, maxY = 31, locationName = "West Beach" };
    locationTableSOTA.loc_east_beach = { index = 2, priority = 1, minX = 51, maxX = 55, minY = 24, maxY = 31, locationName = "East Beach" };
    locationTableSOTA.loc_south_gy = { index = 3, priority = 1, minX = 47, maxX = 50, minY = 54, maxY = 61, locationName = "South Graveyard" };
    locationTableSOTA.loc_courtyard = { index = 4, priority = 1, minX = 44, maxX = 59, minY = 75, maxY = 90, locationName = "Courtyard" };
    locationTableSOTA.loc_east_gy = { index = 5, priority = 1, minX = 52, maxX = 55, minY = 46, maxY = 50, locationName = "East Graveyard" };
    locationTableSOTA.loc_west_gy = { index = 6, priority = 1, minX = 43, maxX = 46, minY = 47, maxY = 52, locationName = "West Graveyard" };
    locationTableSOTA.loc_blue_gate = { index = 7, priority = 1, minX = 56, maxX = 60, minY = 36, maxY = 41, locationName = "Blue Gate" };
    locationTableSOTA.loc_green_gate = { index = 8, priority = 1, minX = 37, maxX = 41, minY = 37, maxY = 42, locationName = "Green Gate" };
    locationTableSOTA.loc_purple_gate = { index = 9, priority = 1, minX = 39, maxX = 42, minY = 55, maxY = 60, locationName = "Purple Gate" };
    locationTableSOTA.loc_red_gate = { index = 10, priority = 1, minX = 56, maxX = 60, minY = 53, maxY = 59, locationName = "Red Gate" };
    locationTableSOTA.loc_yellow_gate = { index = 11, priority = 1, minX = 50, maxX = 53, minY = 68, maxY = 73, locationName = "Yellow Gate" };
    locationTableSOTA.loc_strand_fields = { index = 12, priority = 3, minX = 0, maxX = 100, minY = 0, maxY = 100, locationName = "Strand Field" };
end
-- END LOCATION TABLES --



-- BEGIN GENERAL FUNCTIONS --

function TT_RegisterCommands()
	SLASH_TTLM1 = "/ttlm";
	SlashCmdList["TTLM"] = TT_ShowHelp;

	SLASH_TTLMCONFIG1 = "/ttlm-config";
	SlashCmdList["TTLMCONFIG"] = TT_ShowOptionsPanel;

	SLASH_TTLMSHOWALL1 = "/ttlm-showall";
	SlashCmdList["TTLMSHOWALL"] =  TT_DisplayScore;

	SLASH_TTLMLISTAFK1 = "/ttlm-listafk";
	SlashCmdList["TTLMLISTAFK"] =  TT_DisplayLeechers;

	SLASH_TTLMANNOUNCEAFK1 = "/ttlm-announceafk";
	SlashCmdList["TTLMANNOUNCEAFK"] =  TT_AnnounceLeechers;

	SLASH_TTLMADVERT1 = "/ttlm-advert";
	SlashCmdList["TTLMADVERT"] =  TT_SendAdvert;
end

function TT_ShowHelp()
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33Turing Test Leech Monitor v" .. TT_VERSION .. " by Phobia@Dark Iron [US]");
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33/ttlm-config  --  Display configuration options screen.");
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33/ttlm-listafk  --  List currently identified AFKers.");
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33/ttlm-showall  --  List statistics for all members of current BG.");
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33/ttlm-announceafk  --  Announce the current AFKers in BG chat.");
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33/ttlm-advert  --  Send an advertisement for this mod to BG chat.");
end


function TT_SendAdvert()
	message = "Please report the AFKers and leechers. You can download the 'TuringTest AFK Reporter' mod from Curse/WoWUI/WowInterface which will do it automatically for you. Full explanation on the mod sites."
	SendChatMessage(message, "BATTLEGROUND");
end

function TT_ShowOptionsPanel()
	TT_ConfigFrame:Show();
end


function TT_UpdateBGStatus()
	local newActiveBG = nil;
	local newActiveBGID = nil;

	for i = 1, MAX_BATTLEFIELD_QUEUES do
		local status, mapName, instanceID, lowestLevel, highestLevel, teamSize, registeredMatch = GetBattlefieldStatus(i);
		if(status == "active") then
			newActiveBG = mapName;
			newActiveBGID = instanceID;
			break;
		end
	end

	if(activeBG and (newActiveBG == nil or newActiveBG ~= activeBG)) then
		activeBG = nil;
		activeBGID = 0;
		activeTeamSize = 0;
		timeLastVersionAnnounce = 0;
		expiration = 0;
		timeScoreUpdated = 0;
		playerTable = {};
		TTFrame:SetScript("OnUpdate", nil);
	end

	if(newActiveBG and newActiveBG ~= activeBG) then
		activeBG = newActiveBG;
		activeBGID = newActiveBGID;
		activeTeamSize = teamSize;
		TTFrame:SetScript("OnUpdate", TTFrame_OnUpdate);
		SetMapToCurrentZone(); -- may or may not resolve the periodic problems finding people's locations.
		DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33Battleground '" .. activeBG .. "' starting. Monitoring...");
	end

	if(activeBG and expiration == 0 and GetBattlefieldInstanceExpiration() > 0) then
		expiration = GetBattlefieldInstanceExpiration();
		TT_PrintBGStats();
	end
end


function TT_PrintStats(playerData, header)
	local timeInGame = playerData.lastSeen - playerData.firstSeen;
	local adjustment = TT_CalcEffortAdjustment(timeInGame, playerData.honor);
	local locationID, locationName = TT_DetermineLocation(playerData.posX, playerData.posY);

	message = header;
	if(playerData.simpleName and playerData.simpleRealm) then
		message = message .. " " .. playerData.simpleName .. "-" .. playerData.simpleRealm;
	else
		message = message .. " " .. playerData.name;
	end
	if(averageDamage > 0 and adjustment > 0) then
		message = message .. " dam: " .. playerData.dam .. "(" .. math.floor(100 * playerData.dam / (averageDamage * adjustment)) .. "%)";
	else
		message = message .. " dam: " .. playerData.dam;
	end
	if(averageHeals > 0 and adjustment > 0) then
		message = message .. " heal: " .. playerData.heal .. "(" .. math.floor(100 * playerData.heal / (averageHeals * adjustment)) .. "%)";
	else
		message = message .. " heal: " .. playerData.heal;
	end
	message = message .. " hon: " .. playerData.honor .. "/" .. maxHonor;
	if(timeScoreUpdated > 0 and adjustment > 0) then
		message = message .. " def: " .. math.floor(playerData.timeDefending / 1000) .. "s(" .. math.floor(100 * playerData.timeDefending / (timeScoreUpdated * adjustment)) .. "%)";
	end
	message = message .. " caps: " .. playerData.totalStats;
	message = message .. " time: " .. math.floor(timeInGame / 60000) .. "/" .. math.floor(timeScoreUpdated / 60000) .. "m";
	message = message .. " loc: " .. locationName;
	DEFAULT_CHAT_FRAME:AddMessage(message);
end


function TT_PrintBGStats()
	local bestDam = nil;
	local bestHeal = nil;
	local bestDef = nil;
	local numLeechers = 0;
	local numPlayers = 0;

	for name, playerData in pairs(playerTable) do
		numPlayers = numPlayers + 1;
		if(bestDam == nil or bestDam.dam < playerData.dam) then bestDam = playerData; end
		if(bestHeal == nil or bestHeal.heal < playerData.heal) then bestHeal = playerData; end
		if(bestDef == nil or bestDef.timeDefending < playerData.timeDefending) then bestDef = playerData; end
		if(TT_IsLeecher(playerData)) then numLeechers = numLeechers + 1; end
	end

	if(numPlayers > 0) then
		if(bestDam) then
			TT_PrintStats(bestDam, "|cFF2ADA33<TTLM> Best Damager:");
		end
		if(bestHeal) then
			TT_PrintStats(bestHeal, "|cFF2ADA33<TTLM> Best Healer:");
		end
		if(bestDef and bestDef.timeDefending > 0) then
			TT_PrintStats(bestDef, "|cFF2ADA33<TTLM> Best Defender:");
		end
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> " .. numLeechers .. " total leechers in instance at end of match.");
	end
end


function TT_DisplayScore()
	if(activeBG == nil) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> No active BG.");
		return;
	end

	if(timeScoreUpdated == 0) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> No data recieved yet, please wait...");
		return;
	end

	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Current Game Elapsed Time: " .. math.floor(GetBattlefieldInstanceRunTime() / 1000) .. "s")

	for name, playerData in pairs(playerTable) do
		TT_PrintStats(playerData, "|cFF2ADA33<TTLM>");
	end
end


function TT_DisplayLeechers()
	if(activeBG == nil) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> No active BG.");
		return;
	end

	if(timeScoreUpdated == 0) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> No data recieved yet, please wait...");
		return;
	end

    DEFAULT_CHAT_FRAME:AddMessage("|cFF3ADA33<TTLM> Battleground:  " .. activeBG ) ;
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Elapsed: " .. math.floor(GetBattlefieldInstanceRunTime() / 1000) .. "s Last Update: " .. math.floor((GetBattlefieldInstanceRunTime() - timeScoreUpdated) / 1000) .. "s");
	DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Average Dam: " .. math.floor(averageDamage) .. " Average Heals: " .. math.floor(averageHeals));

	for name, playerData in pairs(playerTable) do
		if(TT_IsLeecher(playerData)) then
			TT_PrintStats(playerData, "|cFF2ADA33<TTLM> Leecher");
		end
	end
end


function TT_AnnounceLeechers()
	if(activeBG == nil) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> No active BG.");
		return;
	end

	if(timeScoreUpdated == 0) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> No data recieved yet, please wait...");
		return;
	end

	local message = "[TTLM] Current Leechers/AFKers:";
	local leechers = 0;
	local totalLeechers = 0;

	for name, playerData in pairs(playerTable) do
		if(TT_IsLeecher(playerData)) then
			leechers = leechers + 1;
			totalLeechers = totalLeechers + 1;
			if(playerData.simpleName and playerData.simpleRealm) then
				message = message .. " " .. playerData.simpleName .. "-" .. playerData.simpleRealm .. ";";
			else
				message = message .. " " .. playerData.name;
			end
			if(leechers == 10) then
				SendChatMessage(message, "BATTLEGROUND");
				message = "[TTLM] Current Leechers/AFKers:";
				leechers = 0;
			end
		end
	end

	if(leechers > 0) then
		SendChatMessage(message, "BATTLEGROUND");
	end

	if(totalLeechers == 0) then
		DEFAULT_CHAT_FRAME:AddMessage("|cFF2ADA33<TTLM> Currently no leechers. Yay!");
	end
end


function TT_ReportLeechers()
	if(activeBG == nil) then return; end
	if(timeScoreUpdated <= 0) then return; end

	-- Disable reporting in arenas.
	if(activeTeamSize and activeTeamSize > 0) then return; end

	thisPlayerName = UnitName("player");

	for name, playerData in pairs(playerTable) do
		--if(playerData.posX == 0 and playerData.posY == 0) then
		--	DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000<TTLM> Error: " .. name .. " (" .. playerData.posX .. "," .. playerData.posY .. ")");
		--end

		--if(playerData.simpleName == nil or playerData.simpleRealm == nil) then
		--	DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000<TTLM> Error: " .. name .. " (nil simpleName or simpleRealm)");
		--end

		if((TT_HasDebuff(name, "Inactive") == false) and (TT_IsLeecher(playerData))) then
			if((playerData.lastReported == 0) or (timeScoreUpdated - playerData.lastReported > 180000)) then
				if(TT_SavedVars.enableReporting and playerData.name ~= thisPlayerName) then
					if(TT_SavedVars.announceReports) then
						TT_PrintStats(playerData, "|cFF7073FF<TTLM> Reporting Leecher");
					end
					ReportPlayerIsPVPAFK(playerData.name);
					playerData.lastReported = timeScoreUpdated;
				else
					if(TT_SavedVars.announceReports) then
						TT_PrintStats(playerData, "|cFF7073FF<TTLM> Identified Leecher");
					end
					playerData.lastReported = timeScoreUpdated;
				end
			end
		end
	end
end


function TT_CalcAverageEffort()
	local totalDamagers = 0;
	local totalHealers = 0;
	local totalDamage = 0;
	local totalHeals = 0;

	maxHonor = 0;
	averageDamage = 0;
	averageHeals = 0;

	for name, playerData in pairs(playerTable) do
		if(playerData.dam > 0) then
			totalDamagers = totalDamagers + 1;
			totalDamage = totalDamage + playerData.dam;
		end

		if(playerData.heal > 0) then
			totalHealers = totalHealers + 1;
			totalHeals = totalHeals + playerData.heal;
		end

		if(maxHonor < playerData.honor) then maxHonor = playerData.honor end
	end

	if(totalDamagers > 0) then 
		averageDamage =  totalDamage / totalDamagers;
	end

	if(totalHealers > 0) then 
		averageHeals =  totalHeals / totalHealers;
	end
end


function TT_CalcEffortAdjustment(timeInGame, playerHonor)
	local percentInGame = 0;
	local percentHonor = 0;
	local percentDefending = 0;
	local adjustment = 1;

	-- What percentage of the game have they been present for?
	percentInGame = timeInGame / timeScoreUpdated;
	
	-- What percentage of the game's honor have they gotten?
	if(maxHonor > 0) then
		percentHonor = playerHonor / maxHonor;
	else
		percentHonor = 0;
	end

	-- Use the larger percentage as an adjustment to our expectations.
	if(percentInGame > percentHonor) then
		adjustment = percentInGame;
	else
		adjustment = percentHonor;
	end

	return adjustment;
end


function TT_IsLeechException_WSG(playerData)
	local timeInGame = playerData.lastSeen - playerData.firstSeen;

	-- Flag carriers are never reported.
	if(TT_HasBuff(playerData.name, TT_WARSONGFLAG)) then
		return true;
	end

	if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 125000) or timeInGame < (TT_SavedVars.timeBeforeReport * 60000)) then
		return true; 
	end
end


function TT_IsLeechException_AB(playerData)
	local timeInGame = playerData.lastSeen - playerData.firstSeen;

	if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 125000) or timeInGame < (TT_SavedVars.timeBeforeReport * 60000)) then 
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAB.loc_alli_entry) == false and playerData.faction == 1) then
			return true;
		end
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAB.loc_horde_entry) == false and playerData.faction == 0) then
			return true;
		end
	end
end


function TT_IsLeechException_EOTS(playerData)
	local timeInGame = playerData.lastSeen - playerData.firstSeen;

	-- Flag carriers are never reported.
	if(TT_HasBuff(playerData.name, TT_NETHERSTORMFLAG)) then
		return true;
	end

	if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 125000) or timeInGame < (TT_SavedVars.timeBeforeReport * 60000)) then 
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableEOTS.loc_alli_entry) == false and playerData.faction == 1) then
			return true;
		end
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableEOTS.loc_horde_entry) == false and playerData.faction == 0) then
			return true;
		end
	end
end

function TT_IsLeechException_AV(playerData)
	local timeInGame = playerData.lastSeen - playerData.firstSeen;

		-- If they're not in the cave, they get five minutes from start or three minutes from joining.
	if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 125000) or timeInGame < (TT_SavedVars.timeBeforeReport * 60000)) then 
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAV.loc_alli_cave) == false and playerData.faction == 1) then
			return true;
		end
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAV.loc_horde_cave) == false and playerData.faction == 0) then
			return true;
		end
	end

		-- If they're in Field of Strife they get two more minutes (they're going somewhere...)
	if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 245000) or timeInGame < ((TT_SavedVars.timeBeforeReport * 60000) + 120000)) then 
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAV.loc_fos_valley) == true ) then
			return true;
		end
	end

		-- If they're in the opposing valley they get another two minutes (making a straight run for the end?)
	if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 365000) or timeInGame < ((TT_SavedVars.timeBeforeReport * 60000) + 240000)) then 
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAV.loc_fw_valley) == true and playerData.faction == 1) then
			return true;
		end
		if(TT_IsInLocation(playerData.posX, playerData.posY, locationTableAV.loc_db_valley) == true and playerData.faction == 0) then
			return true;
		end
	end
 	
		return false;
end


function TT_IsLeecher(playerData)
	local timeInGame = playerData.lastSeen - playerData.firstSeen;


	-- **** EXCEPTIONS **** --

	-- Everyone gets 3 minutes from the start or one minute from joining.
	if(timeScoreUpdated < ((TT_SavedVars.timeLeaveEntrance * 60000) + 125000)) then return false; end
	if(timeInGame < (TT_SavedVars.timeLeaveEntrance * 60000)) then return false; end

	if(activeBG == TT_ALTERACVALLEY) then
		-- Apply Alterac Valley exceptions
		if(TT_IsLeechException_AV(playerData)) then return false; end
	elseif(activeBG == TT_ARATHIBASIN) then
		-- Apply Arathi Basin exceptions
		if(TT_IsLeechException_AB(playerData)) then return false; end
	elseif(activeBG == TT_EYEOFTHESTORM) then
		-- Apply Eye of the Storm exceptions
		if(TT_IsLeechException_EOTS(playerData)) then return false; end
	elseif(activeBG == TT_WARSONGGULCH) then
		-- Apply Warsong Gulch exceptions
		if(TT_IsLeechException_WSG(playerData)) then return false; end
	else
		-- Apply generic exceptions
		if(timeScoreUpdated < ((TT_SavedVars.timeBeforeReport * 60000) + 125000) or timeInGame < (TT_SavedVars.timeBeforeReport * 60000)) then return false; end
	end


	-- **** EFFORT CHECK **** --

	-- Adjustment for percent time in game / percent total honor gained
	local adjustment = TT_CalcEffortAdjustment(timeInGame, playerData.honor);

	-- What percentage of the time have they been defending a node for?
	if(playerData.timeDefending > 0) then
		percentDefending = playerData.timeDefending / timeScoreUpdated;
	else
		percentDefending = 0;
	end
	

	-- Compare their output to the average, adjusted for playtime, with a bonus for defending nodes.
	if(	playerData.dam 
		+ (averageDamage * playerData.totalStats * (TT_SavedVars.pctCaptureBonus / 100))
		+ (averageDamage * percentDefending * (TT_SavedVars.pctDefenseBonus / 100))
		> (averageDamage * adjustment * (TT_SavedVars.minPercentEffort / 100)))
	then 
		return false;
	end

	if(	playerData.heal 
		+ (averageDamage * playerData.totalStats * (TT_SavedVars.pctCaptureBonus / 100))
		+ (averageHeals * percentDefending * (TT_SavedVars.pctDefenseBonus / 100))
		> (averageHeals * adjustment * (TT_SavedVars.minPercentEffort / 100)))
	then 
		return false; 
	end

	return true;
end


function TT_HasDebuff(playerName, debuffName)
	for i=1,40 do
		name, rank, texture, count, debuffType, duration, timeLeft = UnitDebuff(playerName,i);
		if(name == debuffName) then return true; end
		if(name == nil) then return false; end
	end

	return false;
end

-- can we check for honorable defender buff?
function TT_HasBuff(playerName, buffName)
	for i=1,40 do
		name, rank, texture, count, buffType, duration, timeLeft = UnitBuff(playerName,i);
		if(name == buffName) then return true; end
		if(name == nil) then return false; end
	end

	return false;
end


function TT_UpdateScores()

	--if(GetBattlefieldInstanceRunTime() == 0) then
	--	DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000<TTLM> Error: GetBattlefieldInstanceRunTime() == 0");
	--end

	-- Don't update more than once a second (to prevent using too much CPU on a flurry of updates)
	if(GetBattlefieldInstanceRunTime() - timeScoreUpdated < 1000) then return end

	local timeElapsed = GetBattlefieldInstanceRunTime() - timeScoreUpdated;
	timeScoreUpdated = GetBattlefieldInstanceRunTime();
	if(timeScoreUpdated < 1) then return end

	local thisPlayerFaction = UnitFactionGroup("player");

	-- Add or update current scoreboard to table.
	totalScores = GetNumBattlefieldScores();
	for i = 1, totalScores do
		name, kbs, hks, deaths, honor, faction, rank, race, class, filename, dam, heal = GetBattlefieldScore(i);
		unitFaction = UnitFactionGroup(name);
		if(thisPlayerFaction == unitFaction) then
			playerData = playerTable[name];
			if(playerData == nil) then 
				playerData = { firstSeen = timeScoreUpdated, lastReported = 0, timeDefending = 0 };
			end
			playerData.name = name;
			playerData.kbs = kbs;
			playerData.hks = hks;
			playerData.deaths = deaths;
			playerData.honor = honor;
			playerData.faction = faction;
			playerData.rank = rank;
			playerData.race = race;
			playerData.class = class;
			playerData.filename = filename;
			playerData.dam = dam;
			playerData.heal = heal;

			-- Break out name and realm.
			playerData.simpleName, playerData.simpleRealm = UnitName( name );
			if(playerData.simpleName and (playerData.simpleRealm == nil or playerData.simpleRealm == "")) then playerData.simpleRealm = GetCVar("realmName"); end

			-- Get player location and calculate flag defense credit.
			playerData.posX, playerData.posY = GetPlayerMapPosition( name );
			if(TT_IsDefendingNodes(playerData.posX, playerData.posY)) then
				if(UnitIsDeadOrGhost(name) == nil) then
					playerData.timeDefending = playerData.timeDefending + timeElapsed;
				end
			end

			-- Flag carriers get credited with defense time as well.
			if(TT_HasBuff(playerData.name, TT_WARSONGFLAG) or TT_HasBuff(playerData.name, TT_NETHERSTORMFLAG)) then
				playerData.timeDefending = playerData.timeDefending + timeElapsed;
			end


			playerData.lastSeen = timeScoreUpdated;

			local totalStats = 0;
			for j=1, GetNumBattlefieldStats() do
				totalStats = totalStats + GetBattlefieldStatData(i, j);
				playerData[GetBattlefieldStatInfo(j)] = GetBattlefieldStatData(i, j);
			end
			playerData.totalStats = totalStats;

			playerTable[playerData.name] = playerData;
		end
	end

	-- Get player locations, calculate flag defense credit.
	-- TT_UpdatePlayerLocations(timeElapsed);

	-- Remove stale players from table.
	TT_RemoveStalePlayers();

	-- Update damage averages.
	TT_CalcAverageEffort();
end


function TT_RemoveStalePlayers()
	for name, playerData in pairs(playerTable) do
		if(playerData.lastSeen ~= timeScoreUpdated) then
			playerTable[name] = nil;
		end
	end
end


function TT_DetermineLocation(posX, posY)
	posX = math.floor(posX * 100);
	posY = math.floor(posY * 100);

	local locIndex = -1;
	local locName = "";

	if(activeBG and activeBG == TT_ALTERACVALLEY) then
		locIndex, locName = TT_LookupLocation(posX, posY, locationTableAV)
	elseif(activeBG and activeBG == TT_ARATHIBASIN) then
		locIndex, locName = TT_LookupLocation(posX, posY, locationTableAB)
	elseif(activeBG and activeBG == TT_WARSONGGULCH) then
		locIndex, locName = TT_LookupLocation(posX, posY, locationTableWSG)
	elseif(activeBG and activeBG == TT_EYEOFTHESTORM) then
		locIndex, locName = TT_LookupLocation(posX, posY, locationTableEOTS)
    elseif(activeBG and activeBG == TT_ISLEOFCONQUEST) then
        locIndex, locName = TT_LookupLocation(posX, posY, locationTableIoC)
    elseif(activeBG and activeBG == TT_STRANDOFTHEANCIENTS) then
        locIndex, locName = TT_LookupLocation(posX, posY, locationTableSOTA)
	end
	return locIndex, locName;
end


function TT_LookupLocation(posX, posY, locationTable)
	local bestLocIndex = -1;
	local bestLocName = "";
	local bestLocPriority = 99;
	for i,loc in pairs(locationTable) do
		if(posX >= loc.minX and posX <= loc.maxX and posY >= loc.minY and posY <= loc.maxY) then
			if(loc.priority < bestLocPriority) then
				bestLocIndex = i;
				bestLocName = loc.locationName;
				bestLocPriority = loc.priority;
			end
			if(bestLocPriority == 1) then break end
		end
	end
	return bestLocIndex, bestLocName;
end


function TT_IsInLocation(posX, posY, location)
	posX = math.floor(posX * 100);
	posY = math.floor(posY * 100);
	if(posX >= location.minX and posX <= location.maxX and posY >= location.minY and posY <= location.maxY) then
		return true;
	else
		return false;
	end
end


function TT_IsDefendingNodes(posX, posY)
	if(activeBG and activeBG == TT_ALTERACVALLEY) then
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_sp_gy)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_iw_tw)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_sh_gy)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_sh_tw)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_sf_gy)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_ib_tw)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_ib_gy)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_tp_tw)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAV.loc_fw_gy)) then return true; end
	end

	if(activeBG and activeBG == TT_ARATHIBASIN) then
		if(TT_IsInLocation(posX, posY, locationTableAB.loc_stables)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAB.loc_mine)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAB.loc_blacksmith)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAB.loc_mill)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableAB.loc_farm)) then return true; end
	end

	if(activeBG and activeBG == TT_WARSONGGULCH) then
		if(TT_IsInLocation(posX, posY, locationTableWSG.loc_alli_base)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableWSG.loc_horde_base)) then return true; end
	end

	if(activeBG and activeBG == TT_EYEOFTHESTORM) then
		if(TT_IsInLocation(posX, posY, locationTableEOTS.loc_mage_tower)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableEOTS.loc_dranei_ruins)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableEOTS.loc_fel_reaver)) then return true; end
		if(TT_IsInLocation(posX, posY, locationTableEOTS.loc_bloodelf_tower)) then return true; end
	end
    
    if(activeBG and activeBG == TT_ISLEOFCONQUEST) then
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_quarry)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_workshop)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_docks)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_hangar)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_refinery)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_alli_flag)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_alli_turw)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_alli_ture)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_hord_flag)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_hord_turw)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableIoC.loc_hord_ture)) then return true; end
    end
    
    if(activeBG and activeBG == TT_STRANDOFTHEANCIENTS) then
        if(TT_IsInLocation(posX, posY, locationTableSOTA.loc_green_gate)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableSOTA.loc_blue_gate)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableSOTA.loc_purple_gate)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableSOTA.loc_red_gate)) then return true; end
        if(TT_IsInLocation(posX, posY, locationTableSOTA.loc_yellow_gate)) then return true; end        
    end
    
	return false;
end


function TT_InitVariables()
	if(TT_SavedVars.enableReporting == nil) then
		TT_SavedVars.enableReporting = true;
	end
	if(TT_SavedVars.announceReports == nil) then
		TT_SavedVars.announceReports = true;
	end
	if(TT_SavedVars.minPercentEffort == nil) then
		TT_SavedVars.minPercentEffort = 10;
	end
	if(TT_SavedVars.pctDefenseBonus == nil) then
		TT_SavedVars.pctDefenseBonus = 50;
	end
	if(TT_SavedVars.pctCaptureBonus == nil) then
		TT_SavedVars.pctCaptureBonus = 100;
	end
	if(TT_SavedVars.timeLeaveEntrance == nil) then
		TT_SavedVars.timeLeaveEntrance = 1;
	end
	if(TT_SavedVars.timeBeforeReport == nil) then
		TT_SavedVars.timeBeforeReport = 3;
	end
end

-- END GENERAL FUNCTIONS --



-- BEGIN TTFrame FUNCTIONS --

function TTFrame_OnEvent()
	if(event=="UPDATE_BATTLEFIELD_SCORE") then
		if(activeBG and expiration == 0) then
			TT_UpdateScores();
			TT_ReportLeechers();
		end
	elseif(event=="UPDATE_BATTLEFIELD_STATUS") then
		TT_UpdateBGStatus();
	elseif(event=="VARIABLES_LOADED") then
		TT_InitVariables();
	else
	end
end


function TTFrame_OnUpdate(self, elapsed)
	elapsedUpdateRequest = elapsedUpdateRequest + elapsed;
	if(elapsedUpdateRequest > frequencyUpdateRequest) then
		elapsedUpdateRequest = elapsedUpdateRequest - frequencyUpdateRequest;
		RequestBattlefieldScoreData();
	end
end


function TTFrame_Init()
	TTFrame = CreateFrame("Frame");
	TTFrame:SetScript("OnEvent", TTFrame_OnEvent);
	TTFrame:RegisterEvent("UPDATE_BATTLEFIELD_SCORE");
	TTFrame:RegisterEvent("UPDATE_BATTLEFIELD_STATUS");
	TTFrame:RegisterEvent("VARIABLES_LOADED");
	TTFrame:Show();
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33TuringTest Leech Monitor Loaded -- Automatic Battleground AFK and Leech Reporting");
	DEFAULT_CHAT_FRAME:AddMessage("|cFFE34A21<TTLM> |cFF2ADA33v" .. TT_VERSION .. " by Phobia@Dark Iron [US], Updated by Domandred@Shu'halo [US] -- Type '/ttlm' for help.");
end

-- END TTFrame FUNCTIONS --



-- BEGIN INITIALIZATION --

TTFrame_Init();
TT_RegisterCommands();
TT_InitLocations_AV();
TT_InitLocations_AB();
TT_InitLocations_WSG();
TT_InitLocations_EOTS();
TT_InitLocations_IoC();
TT_InitLocations_SOTA();

-- END INITIALIZATION --
